msg_tool\scripts\kirikiri\archive\xp3/
pe.rs

1use super::consts::*;
2use anyhow::Result;
3use memchr::memmem::find;
4use pelite::{PeFile, Wrap};
5
6pub fn get_base_offset<D: AsRef<[u8]> + ?Sized>(data: &D) -> Result<u64> {
7    let file = PeFile::from_bytes(data)?;
8    if let Some(rsrc) = file.section_headers().by_name(".rsrc") {
9        let bytes = file.get_section_bytes(rsrc)?;
10        if let Some(pos) = find(bytes, XP3_MAGIC) {
11            return Ok(rsrc.file_range().start as u64 + pos as u64);
12        }
13    }
14    let last_section_end = file
15        .section_headers()
16        .iter()
17        .map(|s| s.PointerToRawData + s.SizeOfRawData)
18        .max()
19        .unwrap_or_else(|| match file.optional_header() {
20            Wrap::T32(h) => h.SizeOfHeaders,
21            Wrap::T64(h) => h.SizeOfHeaders,
22        });
23    let aligned_offset = ((last_section_end + 0xF) & !0xF) as usize;
24    let data = data.as_ref();
25    if aligned_offset >= data.len() {
26        anyhow::bail!("No overlay for pe image.");
27    }
28    for i in (aligned_offset..(data.len() - 11)).step_by(0x10) {
29        if &data[i..i + 11] == XP3_MAGIC {
30            return Ok(i as u64);
31        }
32    }
33    anyhow::bail!("Failed to find xp3 file in pe file.")
34}